package com.gf.pokemon.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.gf.pokemon.constants.IsSelect;
import com.gf.pokemon.domain.Vote;
import com.gf.pokemon.domain.VoteMsg;
import com.gf.pokemon.domain.VoteOption;
import com.gf.pokemon.domain.VoteUser;
import com.gf.pokemon.domain.VoteUserMsg;
import com.gf.pokemon.domain.VoteUserOption;
import com.gf.pokemon.dto.VoteDto;
import com.gf.pokemon.dto.VoteMsgDto;
import com.gf.pokemon.dto.VoteOptionDto;
import com.gf.pokemon.dto.VoteUserDetailDto;
import com.gf.pokemon.dto.VoteUserDto;
import com.gf.pokemon.dto.VoteUserMsgDto;
import com.gf.pokemon.dto.VoteUserOptionDto;
import com.gf.pokemon.dto.VoteUserStaticsDto;
import com.gf.pokemon.mapper.VoteMapper;
import com.gf.pokemon.mapper.VoteMsgMapper;
import com.gf.pokemon.mapper.VoteOptionMapper;
import com.gf.pokemon.mapper.VoteUserMapper;
import com.gf.pokemon.mapper.VoteUserMsgMapper;
import com.gf.pokemon.mapper.VoteUserOptionMapper;
import com.gf.pokemon.platform.exception.PokeErrorCode;
import com.gf.pokemon.platform.exception.PokeException;
import com.gf.pokemon.util.ConvertUtils;
import com.gf.pokemon.util.PokeUtils;
import com.gf.pokemon.util.page.Page;
import com.gf.pokemon.util.page.PagedList;
import com.gf.pokemon.util.page.PaginationUtil;

@Service
public class VoteUserService {
	
	private final Logger logger = Logger.getLogger(VoteUserService.class);
	
	@Resource
	private VoteUserMapper voteUserMapper;
	
	@Resource
	private VoteUserMsgMapper voteUserMsgMapper;
	
	@Resource
	private VoteUserOptionMapper voteUserOptionMapper;
	
	@Resource
	private VoteMapper voteMapper;
	
	@Resource
	private VoteMsgMapper voteMsgMapper;
	
	@Resource
	private VoteOptionMapper voteOptionMapper;
	
	@Resource
	private VoteService voteService;
	
	@Resource
	private AuserService auserService;
	
	//默认值
	private String DEFAULT_VALUE = "--";
	
	private String MEMO_STR = "选项备注";
	
	private String SHEET_NAME = "投票详情";

	/**
	 * 获取单个用户投票信息
	 * @param voteId
	 * @param voteUserId
	 * @return
	 * @throws PokeException
	 */
	public VoteUserDto getVoteUser(Integer voteId,Integer voteUserId) throws PokeException{
		if(voteId==null || voteUserId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId 或 voteUserId为空");
		}
		VoteUser voteUser = voteUserMapper.selectByPrimaryKey(voteUserId);
		if(voteUser==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票信息不存在");
		}
		VoteUserDto dto = ConvertUtils.convert(voteUser);
		return dto;
	}
	
	/**
	 * 更新用户投票信息
	 * @param voteUserDto
	 * @throws PokeException
	 */
	public void updateVoteUser(VoteUserDto voteUserDto) throws PokeException{
		if(voteUserDto==null || voteUserDto.getId()==null || voteUserDto.getVoteId()==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"无法获取userId、voteId");
		}
		VoteUser voteUser = voteUserMapper.selectByPrimaryKey(voteUserDto.getId());
		if(voteUser==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票人信息不存在");
		}
		Integer voteUserId = voteUserDto.getId();
		Integer voteId = voteUserDto.getVoteId();
		this.deleteVoteUserOptionByUserId(voteId, voteUserId);
		this.saveVoteUserOption(voteId, voteUserId, voteUserDto.getVoteUserOptionDtos());
		this.deleteVoteUserMsgByUserId(voteId, voteUserId);
		this.saveVoteUserMsg(voteId, voteUserId, voteUserDto.getVoteUserMsgDtos());
	}
	
	/**
	 * 保存voteUser
	 * @param voteUserDto
	 * @throws PokeException
	 */
	public void saveVoteUser(VoteUserDto voteUserDto) throws PokeException{
		validate(voteUserDto);	
		VoteUser voteUser = ConvertUtils.convert(voteUserDto);
		voteUser.setCreateDate(Calendar.getInstance().getTime());
		voteUserMapper.insert(voteUser);
		
		this.saveVoteUserOption(voteUser.getVoteId(), voteUser.getId(), voteUserDto.getVoteUserOptionDtos());
		this.saveVoteUserMsg(voteUser.getVoteId(), voteUser.getId(), voteUserDto.getVoteUserMsgDtos());
		
		//关闭oa流程
		auserService.sendCloseOARequest(voteUserDto.getOaUser(), voteUserDto.getVoteId().toString());
	}
	
	/**
	 * 删除用户的投票选项
	 * @param voteId
	 * @param voteUserId
	 * @throws PokeException
	 */
	public void deleteVoteUserOptionByUserId(Integer voteId,Integer voteUserId) throws PokeException{
		if(voteId==null || voteUserId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId或voteUserId为空");
		}
		voteUserOptionMapper.deleteByVoteUserId(voteId, voteUserId);
	}
	
	/**
	 * 删除用户的投票信息
	 * @param voteId
	 * @param voteUserId
	 * @throws PokeException
	 */
	public void deleteVoteUserMsgByUserId(Integer voteId,Integer voteUserId) throws PokeException{
		if(voteId==null || voteUserId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId或voteUserId为空");
		}
		voteUserMsgMapper.deleteByVoteUserId(voteId, voteUserId);
	}
	
	/**
	 * 保存用户选择的选项
	 * @param voteId
	 * @param userId
	 * @param voteUserOptions
	 * @throws PokeException
	 */
	public void saveVoteUserOption(Integer voteId, Integer userId,List<VoteUserOptionDto> voteUserOptions) throws PokeException{
		if(voteId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空");
		}
		if(userId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"userId为空");
		}
		if(CollectionUtils.isEmpty(voteUserOptions)){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"选项为空");
		}
		List<Integer> voteOptionIds = new ArrayList<Integer>();
		for(VoteUserOptionDto dto : voteUserOptions){
			if(dto!=null){
				voteOptionIds.add(dto.getVoteOptionId());
			}
		}
		List<VoteOption> voteOptionDtos= voteOptionMapper.findByIds(voteOptionIds);
		if(voteOptionIds.size()!=voteOptionDtos.size()){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票选项不存在:"+voteOptionIds);
		}
		for(VoteUserOptionDto dto:voteUserOptions){
			if(dto!=null){
				VoteUserOption voteUserOption = ConvertUtils.convert(dto);
				voteUserOption.setVoteId(voteId);
				voteUserOption.setVoteUserId(userId);
				voteUserOptionMapper.insert(voteUserOption);
			}
		}
	}
	
	/**
	 * 保存用户信息
	 * @param voteId
	 * @param userId
	 * @param voteUserMsgs
	 * @throws PokeException
	 */
	public void saveVoteUserMsg(Integer voteId, Integer userId,List<VoteUserMsgDto> voteUserMsgs) throws PokeException{
		if(voteId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空");
		}
		if(userId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"userId为空");
		}
		if(CollectionUtils.isNotEmpty(voteUserMsgs)){
			List<Integer> voteMsgIds = new ArrayList<Integer>();
			for(VoteUserMsgDto dto:voteUserMsgs){
				voteMsgIds.add(dto.getVoteMsgId());
			}
			List<VoteMsg> msgs = voteMsgMapper.findByIds(voteMsgIds);
			if(msgs.size()!=voteMsgIds.size()){
				throw new PokeException(PokeErrorCode.INVALID_PARAM,"提交内容不存在:"+voteMsgIds);
			}
			for(VoteUserMsgDto dto:voteUserMsgs){
				VoteUserMsg voteUserMsg = ConvertUtils.convert(dto);
				voteUserMsg.setVoteId(voteId);
				voteUserMsg.setVoteUserId(userId);
				voteUserMsgMapper.insert(voteUserMsg);
			}
		}
	}
	
	/**
	 * 获取投票的统计值
	 * @param voteId
	 * @return
	 * @throws PokeException
	 */
	public VoteUserStaticsDto getStaticsByVoteId(Integer voteId) throws PokeException{
		if(voteId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空");
		}
		VoteDto voteDto = voteService.getVoteById(voteId);
		if(voteDto==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题不存在");
		}
		List<VoteUser> voteUsers = voteUserMapper.getVoteUserByVoteId(voteId);		
		return statics(voteDto,voteUsers);
	}
	
	/**
	 * 获取投票详情的标题头
	 * @param voteId
	 * @return
	 * @throws PokeException
	 */
	public List<String> getVoteDetailTitle(Integer voteId) throws PokeException{
		if(voteId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空");
		}
		
		VoteDto dto = voteService.getVoteById(voteId);
		if(dto==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题不存在");
		}
		
		List<String> title = new ArrayList<String>();
		
		if(CollectionUtils.isNotEmpty(dto.getVoteMsgDtos())){
			for(VoteMsgDto voteMsgDto:dto.getVoteMsgDtos()){
				title.add(voteMsgDto.getMsg());
			}
		}
		//然后获取用户选项细节
		//先获取用户填写细节
		if(CollectionUtils.isNotEmpty(dto.getVoteOptionDtos())){
			for(VoteOptionDto voteOptionDto:dto.getVoteOptionDtos()){
				title.add(voteOptionDto.getOptionstr());
				title.add(MEMO_STR);
			}
		}
		return title;
		
	}
	
	/**
	 * 分页获取每个用户的投票细节
	 * @param voteId
	 * @param page
	 * @return
	 * @throws PokeException
	 */
	public PagedList<VoteUserDetailDto> getVoteDetailByPage(final Integer voteId,Page page) throws PokeException{
		if(voteId==null || page==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空 或 无分页信息");
		}
		PagedList<VoteUser> pagedQuery = PaginationUtil.pagedQuery(page, new Callable<List<VoteUser>>() {            
            public List<VoteUser> call() throws Exception {
                return voteUserMapper.getVoteUserByVoteId(voteId);
            }
        });
		
		VoteDto dto = voteService.getVoteById(voteId);
		if(dto==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题不存在");
		}
		
		if(CollectionUtils.isEmpty(pagedQuery.getList())){
			return new PagedList<VoteUserDetailDto>(pagedQuery.getPage(),
					new ArrayList<VoteUserDetailDto>());
		}
		
		List<VoteUserDetailDto> details = generateUserDetail(dto,pagedQuery.getList());
		
		return new PagedList<VoteUserDetailDto>(pagedQuery.getPage(),details);
	}
	
	/**
	 * 获取每个用户的投票细节Excel
	 * @param voteId
	 */
	public byte[] getVoteDetailByPageExcel(Integer voteId) throws PokeException{
		if(voteId==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"voteId为空");
		}
		VoteDto voteDto = voteService.getVoteById(voteId);
		if(voteDto==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题不存在");
		}
		List<String> excelHeaders = this.getVoteDetailTitle(voteId);
		List<VoteUser> voteUsers = voteUserMapper.getVoteUserByVoteId(voteId);
		
		List<VoteUserDetailDto> userDetails = this.generateUserDetail(voteDto, voteUsers);
		
		List<List<String>> excelDatas = new ArrayList<List<String>>();
		for(VoteUserDetailDto voteUserDetailDto : userDetails){
			excelDatas.add(voteUserDetailDto.getData());
		}
		
		return PokeUtils.buildExcelData(SHEET_NAME, excelHeaders, excelDatas);
	}
	
	/**
	 * 根据投票主题及用户投票信息，构造用户投票细节Dto
	 * @param dto
	 * @param voteUsers
	 * @return
	 */
	private List<VoteUserDetailDto> generateUserDetail(VoteDto dto,List<VoteUser> voteUsers) {
		List<VoteUserDetailDto> details = new ArrayList<VoteUserDetailDto>();
		if(dto==null || CollectionUtils.isEmpty(voteUsers)){
			return details;
		}		
		for(VoteUser voteUser:voteUsers){
			VoteUserDetailDto voteUserDetail = new VoteUserDetailDto();
			voteUserDetail.setVoteUserId(voteUser.getId());
			Map<Integer, VoteUserMsg> userMsgMap = ConvertUtils.convertToVoteUserMsgMap(voteUser.getVoteUserMsgs());
			Map<Integer, VoteUserOption> userOptionMap = ConvertUtils.convertToVoteUserOptionMap(voteUser.getVoteUserOptions());
			//先获取用户填写细节
			if(CollectionUtils.isNotEmpty(dto.getVoteMsgDtos())){
				for(VoteMsgDto voteMsgDto:dto.getVoteMsgDtos()){
					VoteUserMsg msg = userMsgMap.get(voteMsgDto.getId());
					if(msg!=null){
						voteUserDetail.addData(msg.getMsgValue());
					}else{
						voteUserDetail.addData(DEFAULT_VALUE);
					}
				}
			}
			//然后获取用户选项细节
			//先获取用户填写细节
			if(CollectionUtils.isNotEmpty(dto.getVoteOptionDtos())){
				for(VoteOptionDto voteOptionDto:dto.getVoteOptionDtos()){
					VoteUserOption option = userOptionMap.get(voteOptionDto.getId());
					if(option!=null){
						voteUserDetail.addData(option.getIsSelect().toString());
						voteUserDetail.addData(option.getOptionNum()==null?"--":option.getOptionNum().toString());
					}else{
						voteUserDetail.addData(DEFAULT_VALUE);
						voteUserDetail.addData(DEFAULT_VALUE);
					}
				}
			}
			details.add(voteUserDetail);
		}
		return details;
	}
	
	/**
	 * 统计投票信息
	 * @param voteDto
	 * @param voteUsers
	 * @return
	 */
	private VoteUserStaticsDto statics(VoteDto voteDto,List<VoteUser> voteUsers){
		Map<Integer, VoteOptionDto> map = ConvertUtils
				.convertToOptionDtoMap(voteDto.getVoteOptionDtos());
		VoteUserStaticsDto voteStatics = new VoteUserStaticsDto();
		//有人投票，才开始统计
		if(voteDto==null || CollectionUtils.isEmpty(voteUsers)){
			return voteStatics;
		}
		voteStatics.setVoteTitle(voteDto.getTitle());
		voteStatics.setOptionNum(voteDto.getVoteOptionDtos().size());
		voteStatics.setVmode(Integer.valueOf(voteDto.getVmode()));
		for(VoteUser voteUser:voteUsers){
			//加一个人投票记录
			voteStatics.addVoteNum(1);
			//加这个人投了哪些选项的记录
			List<VoteUserOption> userOptions = voteUser
					.getVoteUserOptions();
			for(VoteUserOption userOption:userOptions){
				//选中的记录才会统计
				if (IsSelect.YES.getType().equals(
						Integer.valueOf(userOption.getIsSelect()))) {
					voteStatics.addVoteTotalNum(1);
					VoteOptionDto voteOptionDto = map.get(userOption
							.getVoteOptionId());
					if(voteOptionDto==null){
						continue;
					}
					voteStatics.addStaticsOption(userOption.getVoteOptionId(),
							voteOptionDto.getOptionstr(), userOption.getOptionNum());
					
				}
				
			}
		}
		voteStatics.sortStaticsOption();
		return voteStatics;
	}
	
	private void validate(VoteUserDto voteUser) throws PokeException {
		if(voteUser==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM);
		}
		if(voteUser.getVoteId()==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题Id为空");
		}
		
		Vote vote = voteMapper.selectByPrimaryKey(voteUser.getVoteId());
		if(vote==null){
			throw new PokeException(PokeErrorCode.INVALID_PARAM,"投票主题不存在:"+voteUser.getVoteId());
		}
	}

	public VoteUserMapper getVoteUserMapper() {
		return voteUserMapper;
	}

	public void setVoteUserMapper(VoteUserMapper voteUserMapper) {
		this.voteUserMapper = voteUserMapper;
	}

	public VoteUserMsgMapper getVoteUserMsgMapper() {
		return voteUserMsgMapper;
	}

	public void setVoteUserMsgMapper(VoteUserMsgMapper voteUserMsgMapper) {
		this.voteUserMsgMapper = voteUserMsgMapper;
	}

	public VoteUserOptionMapper getVoteUserOptionMapper() {
		return voteUserOptionMapper;
	}

	public void setVoteUserOptionMapper(VoteUserOptionMapper voteUserOptionMapper) {
		this.voteUserOptionMapper = voteUserOptionMapper;
	}

	public VoteService getVoteService() {
		return voteService;
	}

	public void setVoteService(VoteService voteService) {
		this.voteService = voteService;
	}
	
}
